#pragma once

#include <iostream>
#include <string>
#include <cstring>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <pthread.h>

class Sock
{
public:
    Sock() {}  // 默认构造函数
    ~Sock() {} // 析构函数

    // 创建socket文件描述符
    static int Socket()
    {
        int sock = socket(AF_INET, SOCK_STREAM, 0);
        if (sock < 0)
        {
            return -1;
        }

        return sock;
    }

    // 绑定端口号
    static int Bind(int sock, const std::string &ip, uint16_t port)
    {
        struct sockaddr_in tmp;
        memset(&tmp, 0, sizeof(tmp));
        tmp.sin_family = AF_INET;                    // 网络协议族
        tmp.sin_addr.s_addr = inet_addr(ip.c_str()); // ip地址
        tmp.sin_port = htons(port);                  // 端口号
        socklen_t len = sizeof(tmp);

        if (bind(sock, (struct sockaddr *)&tmp, len) < 0)
        {
            return -1;
        }

        return 0;
    }

    // 设置监听状态
    static int Listen(int sock, int backlog)
    {
        if (listen(sock, backlog) < 0)
        {
            return -1;
        }

        return 0;
    }

    // 接受连接
    static int Accept(int sock, std::string *ip, uint16_t *port)
    {
        struct sockaddr_in peer;
        memset(&peer, 0, sizeof(peer));
        socklen_t len = sizeof(peer);

        int fd = accept(sock, (struct sockaddr *)&peer, &len);
        if (fd < 0)
            return -1;

        if (ip)
            *ip = inet_ntoa(peer.sin_addr);
        if (port)
            *port = ntohs(peer.sin_port);

        return fd;
    }

    // 连接对方
    static int Connect(int sock, const std::string &ip, uint16_t port)
    {
        struct sockaddr_in peer;
        memset(&peer, 0, sizeof(peer));

        peer.sin_family = AF_INET;
        peer.sin_addr.s_addr = inet_addr(ip.c_str());
        peer.sin_port = htons(port);

        socklen_t len = sizeof(peer);

        if (connect(sock, (const struct sockaddr *)&peer, len) < 0)
        {
            return -1;
        }

        return 0;
    }
};
